#include "GLBitmap.h"

GLBitmap::GLBitmap( string filename )
{
	//-- Dateinamen Sichern
	_filename = filename;
	
	//-- Prüfen ob "int" aus 32 bit besteht
	if(sizeof(int)!=4) 
		throw "GLBitmap::GLBitmap()<!!! - int - is not 32 bit !!!>";
 
 	//Datei öffnen zum lesen in binär modus
	FILE* f=fopen(filename.c_str(),"rb");		
	
	if(!f) 
		throw "GLBitmap::GLBitmap()<!!! Opening file failed !!!>";
		
	//-- Headerinformationen
	char header[54];
	fread(header,54,1,f);			//read the 54bit main header

	if(header[0]!='B' || header[1]!='M') 
	{
		fclose(f);
			throw "GLBitmap::GLBitmap()<!!! Bitmap Header invalid !!!>";		//all bitmaps should start "BM"
	}

	//it seems gimp sometimes makes its headers small, so we have to do this. hence all the fseeks
	int offset=*(unsigned int*)(header+10);
	
	_width=*(int*)(header+18);
	_height=*(int*)(header+22);
	//now the bitmap knows how big it is it can allocate its memory
	_data = new BYTE[_width*_height*3];

	int bits=int(header[28]);		//farbtiefe

	int x,y,c;
	BYTE cols[256*4];				//colourtable
	switch(bits)
	{
	case(24):
		fseek(f,offset,SEEK_SET);
		fread(_data,_width*_height*3,1,f);	//24bit is easy
		for(x=0;x<_width*_height*3;x+=3)			//opengl format ist RGB
		{											//dieses ist BGR also umwandeln!!!
			BYTE temp=_data[x];
			_data[x]=_data[x+2];
			_data[x+2]=temp;
		}
		break;

	case(8):
		fread(cols,256*4,1,f);							//read colortable
		fseek(f,offset,SEEK_SET);
		for(y=0;y<_height;++y)						//(Notice 4bytes/col for some reason)
			for(x=0;x<_width;++x)
			{
				BYTE byte;			
				fread(&byte,1,1,f);						//just read byte					
				for(int c=0;c<3;++c)
					pixel(x,y,c)=cols[byte*4+2-c];	//and look up in the table
			}
		break;

	case(4):
		fread(cols,16*4,1,f);
		fseek(f,offset,SEEK_SET);
		for(y=0;y<256;++y)
			for(x=0;x<256;x+=2)
			{
				BYTE byte;
				fread(&byte,1,1,f);						//as above, but need to exract two
				for(c=0;c<3;++c)						//pixels from each byte
					pixel(x,y,c)=cols[byte/16*4+2-c];
				for(c=0;c<3;++c)
					pixel(x+1,y,c)=cols[byte%16*4+2-c];
			}
		break;

	case(1):
		fread(cols,8,1,f);
		fseek(f,offset,SEEK_SET);
		for(y=0;y<_height;++y)
			for(x=0;x<_width;x+=8)
			{
				BYTE byte;
				fread(&byte,1,1,f);
				//Every byte is eight pixels
				//so I'm shifting the byte to the relevant position, then masking out
				//all but the lowest bit in order to get the index into the colourtable.
				for(int x2=0;x2<8;++x2)
					for(int c=0;c<3;++c)
						pixel(x+x2,y,c)=cols[((byte>>(7-x2))&1)*4+2-c];
			}
		break;

	default:
		fclose(f);
		throw "GLBitmap::GLBitmap()<!!! Unbekanntest Format !!!>";
	}

	if(ferror(f))
	{
		fclose(f);
		throw "GLBitmap::GLBitmap()<!!! Bitmap Datei Fehler !!!>";
	}
	
	fclose(f);
}

BYTE& GLBitmap::pixel(int x,int y,int c)
{
	return _data[(y*_width+x)*3+c];
}
